/* gvSIG. Sistema de Informaci�n Geogr�fica de la Generalitat Valenciana * * Copyright (C) 2004-2007 IVER T.I. and Generalitat Valenciana. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,USA. * * For more information, contact: * * Generalitat Valenciana * Conselleria d'Infraestructures i Transport * Av. Blasco Ib��ez, 50 * 46010 VALENCIA * SPAIN * * +34 963862235 * gvsig@gva.es * www.gvsig.gva.es * * or * * IVER T.I. S.A * Salamanca 50 * 46005 Valencia * Spain * * +34 963163400 * dac@iver.es */ package com.iver.andami; import java.awt.Component; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.Frame; import java.awt.KeyboardFocusManager; import java.awt.Point; import java.awt.Toolkit; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.File; import java.io.FileFilter; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.Reader; import java.net.Authenticator; import java.net.MalformedURLException; import java.net.PasswordAuthentication; import java.net.URL; import java.nio.channels.FileChannel; import java.security.AllPermission; import java.security.CodeSource; import java.security.PermissionCollection; import java.security.Permissions; import java.security.Policy; import java.util.ArrayList; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Locale; import java.util.TreeMap; import java.util.prefs.Preferences; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JOptionPane; import javax.swing.JPopupMenu; import javax.swing.SwingUtilities; import javax.swing.UIManager; import org.apache.log4j.Logger; import org.apache.log4j.PatternLayout; import org.apache.log4j.PropertyConfigurator; import org.apache.log4j.RollingFileAppender; import org.exolab.castor.xml.MarshalException; import org.exolab.castor.xml.ValidationException; import com.iver.andami.authentication.IAuthentication; import com.iver.andami.authentication.LoginUI; import com.iver.andami.config.generate.Andami; import com.iver.andami.config.generate.AndamiConfig; import com.iver.andami.config.generate.Plugin; import com.iver.andami.iconthemes.IIconTheme; import com.iver.andami.iconthemes.IconThemeManager; import com.iver.andami.messages.Messages; import com.iver.andami.messages.NotificationManager; import com.iver.andami.plugins.ExclusiveUIExtension; import com.iver.andami.plugins.ExtensionDecorator; import com.iver.andami.plugins.IExtension; import com.iver.andami.plugins.PluginClassLoader; import com.iver.andami.plugins.config.generate.ActionTool; import com.iver.andami.plugins.config.generate.ComboButton; import com.iver.andami.plugins.config.generate.ComboButtonElement; import com.iver.andami.plugins.config.generate.ComboScale; import com.iver.andami.plugins.config.generate.Depends; import com.iver.andami.plugins.config.generate.Extension; import com.iver.andami.plugins.config.generate.Extensions; import com.iver.andami.plugins.config.generate.LabelSet; import com.iver.andami.plugins.config.generate.Menu; import com.iver.andami.plugins.config.generate.PluginConfig; import com.iver.andami.plugins.config.generate.PopupMenu; import com.iver.andami.plugins.config.generate.PopupMenus; import com.iver.andami.plugins.config.generate.SelectableTool; import com.iver.andami.plugins.config.generate.SkinExtension; import com.iver.andami.plugins.config.generate.SkinExtensionType; import com.iver.andami.plugins.config.generate.ToolBar; import com.iver.andami.plugins.status.IExtensionStatus; import com.iver.andami.plugins.status.IUnsavedData; import com.iver.andami.ui.AndamiEventQueue; import com.iver.andami.ui.MDIManagerLoadException; import com.iver.andami.ui.fonts.FontUtils; import com.iver.andami.ui.mdiFrame.MDIFrame; import com.iver.andami.ui.mdiFrame.NewStatusBar; import com.iver.andami.ui.mdiManager.MDIManagerFactory; import com.iver.andami.ui.splash.MultiSplashWindow; import com.iver.andami.ui.theme.Theme; import com.iver.andami.ui.wizard.UnsavedDataPanel; import com.iver.utiles.DateTime; import com.iver.utiles.FileUtils; import com.iver.utiles.XMLEntity; import com.iver.utiles.xml.XMLEncodingUtils; import com.iver.utiles.xmlEntity.generate.XmlTag; /** * <p> * Andami's launching class. This is the class used to create the Andami's * plugin environment.<br> * </p> * * <p> * <b>Syntax:</b> <br> * java [-Xmx512M (for 512MB of RAM)] [-classpath={a colon-separated(unix) or * semicolon-separated(windows) list of files containg base library of classes}] * [-Djava.library.path=PATH_TO_NATIVE_LIBRARIES] * PATH_TO_APPLICATION_HOME_DIRECTORY PATH_TO_APPLICATION_PLUGINS_DIRECTORY * [{list of additional custom application arguments separated by spaces}] * </p> * * * @author $author$ * @version $Revision: 33300 $ */ public class Launcher { private static Logger logger = Logger.getLogger(Launcher.class.getName()); private static Preferences prefs = Preferences.userRoot().node( "gvsig.connection"); private static AndamiConfig andamiConfig; private static MultiSplashWindow splashWindow; private static String appName; private static Locale locale; private static HashMap<String, PluginConfig> pluginsConfig = new HashMap<String, PluginConfig>(); private static HashMap<String, PluginServices> pluginsServices = new HashMap<String, PluginServices>(); private static MDIFrame frame; private static HashMap<Class<?>, ExtensionDecorator> classesExtensions = new HashMap<Class<?>, ExtensionDecorator>(); private static String andamiConfigPath; private static String pluginsPersistencePath; private static final String nonWinDefaultLookAndFeel = "com.jgoodies.looks.plastic.PlasticXPLookAndFeel"; private static ArrayList<String> pluginsOrdered = new ArrayList<String>(); private static ArrayList<IExtension> extensions = new ArrayList<IExtension>(); private static String appHomeDir = null; // it seems castor uses this encoding private static final String CASTORENCODING = "UTF8"; private static final class ProxyAuth extends Authenticator { private PasswordAuthentication auth; private ProxyAuth(String user, String pass) { auth = new PasswordAuthentication(user, pass.toCharArray()); } protected PasswordAuthentication getPasswordAuthentication() { return auth; } } public static void main(String[] args) throws Exception { try { if (!validJVM()) { System.exit(-1); } if (args.length < 1) { System.err .println("Uso: Launcher appName plugins-directory [language=locale]"); } // Clean temporal files Utilities.cleanUpTempFiles(); appName = args[0]; appHomeDir = System.getProperty(args[0] + ".home"); if (appHomeDir == null) appHomeDir = System.getProperty("user.home"); appHomeDir += File.separator + args[0] + File.separator; // If gvSIG.confDir exists, then it will override any other setting // for // the configuration file path. // This is a Java property, which means it has to be passed to the // VM like this: java -DgvSIG.confDir=<path> String gvsig_conf_dir = System.getProperty("gvSIG.confDir"); if (gvsig_conf_dir != null) { gvsig_conf_dir = gvsig_conf_dir.trim(); if (gvsig_conf_dir.length() > 0) { if (gvsig_conf_dir.endsWith(File.separator)) { appHomeDir = gvsig_conf_dir; } else { appHomeDir = gvsig_conf_dir + File.separator; } } } FileUtils.setAppHomeDir(appHomeDir); logger.debug("User settings will be stored in: " + appHomeDir); File parent = new File(appHomeDir); parent.mkdirs(); andamiConfigPath = appHomeDir + "andami-config.xml"; pluginsPersistencePath = appHomeDir + "plugins-persistence.xml"; // Configurar el log4j Launcher.class.getClassLoader().getResource("."); PropertyConfigurator.configure("log4j.properties"); PatternLayout l = new PatternLayout("%p %t %C - %m%n"); RollingFileAppender fa = new RollingFileAppender(l, appHomeDir + args[0] + ".log", false); fa.setMaxFileSize("512KB"); fa.setMaxBackupIndex(3); Logger.getRootLogger().addAppender(fa); // Leer el fichero de configuraci�n de andami (andami-config.xsd) // locale // Buscar actualizaci�nes al comenzar // Andami // Plugins // Directorio de las extensiones andamiConfigFromXML(andamiConfigPath); andamiConfig.setPluginsDirectory(args[1]); // Hacemos visibles los argumentos como una propiedad est�tica // de plugin services para quien lo quiera usar (por ejemplo, para // cargar un proyecto por l�nea de comandos) PluginServices.setArguments(args); configureLocales(args); // Se pone el lookAndFeel try { String lookAndFeel = getAndamiConfig().getLookAndFeel(); if (lookAndFeel == null) lookAndFeel = getDefaultLookAndFeel(); UIManager.setLookAndFeel(lookAndFeel); } catch (Exception e) { logger.warn(Messages.getString("Launcher.look_and_feel"), e); } FontUtils.initFonts(); // Solucionamos el problema de permisos que se produc�a con Java // Web Start con este c�digo. // System.setSecurityManager(null); Policy.setPolicy(new Policy() { public PermissionCollection getPermissions(CodeSource codesource) { Permissions perms = new Permissions(); perms.add(new AllPermission()); return (perms); } public void refresh() { } }); initIconThemes(); // Registramos los iconos base registerIcons(); validate(); // Obtener la personalizaci�n de la aplicaci�n. Theme theme = getTheme(); // Mostrar la ventana de inicio Frame f = new Frame(); splashWindow = new MultiSplashWindow(f, theme, 190); // 1. Ponemos los datos del proxy splashWindow.process(10, PluginServices.getText(Launcher.class, "SplashWindow.configuring_proxy")); configureProxy(); // 3. Se leen los config.xml de los plugins -----++++ splashWindow.process(30, PluginServices.getText(Launcher.class, "SplashWindow.reading_plugins_config.xml")); loadPlugins(andamiConfig.getPluginsDirectory()); // 4. Se configura el classloader del plugin splashWindow.process(40, PluginServices.getText(Launcher.class, "SplashWindow.setting_up_class_loaders")); pluginsClassLoaders(); // 5. Se carga un Skin si alguno de los plugins trae informaci�n // para ello splashWindow.process(50, PluginServices.getText(Launcher.class, "SplashWindow.looking_for_a_skin")); skinPlugin(null); // 6. Se configura la cola de eventos splashWindow.process(60, PluginServices.getText(Launcher.class, "setting_up_event_queue")); EventQueue waitQueue = new AndamiEventQueue(); Toolkit.getDefaultToolkit().getSystemEventQueue().push(waitQueue); // 7. Se configura la mensajer�a del plugin splashWindow .process( 70, PluginServices .getText(Launcher.class, "SplashWindow.starting_plugin_internationalization_system")); pluginsMessages(); // 8. Se modifica el andami-config con los plugins nuevos splashWindow.process(80, PluginServices.getText(Launcher.class, "SplashWindow.looking_for_a_skin")); updateAndamiConfig(); frame = new MDIFrame(); // 9. Se configura el nombre e icono de la aplicaci�n splashWindow.process(90, PluginServices.getText(Launcher.class, "SplashWindow.setting_up_applications_name_and_icons")); frameIcon(theme); // 10. Se prepara el MainFrame para albergar las extensiones splashWindow.process(100, PluginServices.getText(Launcher.class, "SplashWindow.preparing_workbench")); JPopupMenu.setDefaultLightWeightPopupEnabled(false); SwingUtilities.invokeAndWait(new Runnable() { public void run() { frame.init(); } }); // 11. Leer el fichero de persistencia // info de los plugins // bookmarks de los plugins splashWindow.process(110, PluginServices.getText(Launcher.class, "SplashWindow.loading_plugin_settings")); loadPluginsPersistence(); // Se instalan los controles del skin // 12. Se inicializan todas las extensiones de todos los plugins splashWindow.process(120, PluginServices.getText(Launcher.class, "SplashWindow.initializing_extensions")); SwingUtilities.invokeAndWait(new Runnable() { public void run() { initializeExtensions(); } }); // 13. Se inicializan la extensi�n exclusiva splashWindow.process(130, PluginServices.getText(Launcher.class, "SplashWindow.setting_up_master_extension")); SwingUtilities.invokeAndWait(new Runnable() { public void run() { initializeExclusiveUIExtension(); } }); frame.setClassesExtensions(classesExtensions); // 14. Se instalan los controles de las extensiones de los plugins splashWindow.process(140, PluginServices.getText(Launcher.class, "SplashWindow.installing_extensions_controls")); SwingUtilities.invokeAndWait(new Runnable() { public void run() { installPluginsControls(); } }); // 15. Se instalan los menus de las extensiones de los plugins splashWindow.process(150, PluginServices.getText(Launcher.class, "SplashWindow.installing_extensions_menus")); SwingUtilities.invokeAndWait(new Runnable() { public void run() { installPluginsMenus(); } }); // 16. Se instalan las etiquetas de las extensiones de los plugins splashWindow.process(160, PluginServices.getText(Launcher.class, "SplashWindow.installing_extensions_labels")); SwingUtilities.invokeAndWait(new Runnable() { public void run() { installPluginsLabels(); } }); // 17. Se instalan los bookmarks de los plugins // 18. Se muestra el frame principal splashWindow.process(180, PluginServices.getText(Launcher.class, "creating_main_window")); frame.setVisible(true); // 19. Se ejecuta el postInitialize splashWindow.process(190, PluginServices.getText(Launcher.class, "SplashWindow.post_initializing_extensions")); SwingUtilities.invokeAndWait(new Runnable() { public void run() { postInitializeExtensions(); } }); // Definimos un KeyEventDispatcher global para que las extensiones // puedan registrar sus "teclas r�pidas". GlobalKeyEventDispatcher keyDispatcher = GlobalKeyEventDispatcher .getInstance(); KeyboardFocusManager.getCurrentKeyboardFocusManager() .addKeyEventDispatcher(keyDispatcher); SwingUtilities.invokeAndWait(new Runnable() { public void run() { frame.enableControls(); } }); splashWindow.close(); } catch (Exception e) { logger.error("excepci�n al arrancar", e); System.exit(-1); } } private static void registerIcons() { PluginServices.getIconTheme().registerDefault( "login-gvsig", LoginUI.class.getClassLoader().getResource( "images/login_gvsig.png")); PluginServices.getIconTheme().registerDefault( "splash-gvsig", MultiSplashWindow.class.getClassLoader().getResource( "images/splash.png")); PluginServices.getIconTheme().registerDefault( "info-icon", NewStatusBar.class.getClassLoader().getResource( "images/info.gif")); PluginServices.getIconTheme().registerDefault( "error-icon", NewStatusBar.class.getClassLoader().getResource( "images/error.gif")); PluginServices.getIconTheme().registerDefault( "warning-icon", NewStatusBar.class.getClassLoader().getResource( "images/warning.gif")); PluginServices.getIconTheme().registerDefault( "no-icon", NewStatusBar.class.getClassLoader().getResource( "images/no_icon.png")); } /** * Obtiene la personalizaci�n de los iconos, splash, fondo y el nombre de la * aplicaci�n. * * @return Theme */ private static Theme getTheme() { Theme theme = new Theme(); String name = PluginServices.getArgumentByName("andamiTheme"); // File file=new File("theme/andami-theme.xml"); File file; if (name == null) { file = new File("theme/andami-theme.xml"); } else { file = new File(name); } if (file.exists()) { theme.readTheme(file); } return theme; } /** * Establece los datos que ten�amos guardados respecto de la configuraci�n * del proxy. */ private static void configureProxy() { String host = prefs.get("firewall.http.host", ""); String port = prefs.get("firewall.http.port", ""); System.getProperties().put("http.proxyHost", host); System.getProperties().put("http.proxyPort", port); // Ponemos el usuario y clave del proxy, si existe String proxyUser = prefs.get("firewall.http.user", null); String proxyPassword = prefs.get("firewall.http.password", null); if (proxyUser != null) { System.getProperties().put("http.proxyUserName", proxyUser); System.getProperties().put("http.proxyPassword", proxyPassword); Authenticator.setDefault(new ProxyAuth(proxyUser, proxyPassword)); } else { Authenticator.setDefault(new ProxyAuth("", "")); } } /** * Recupera la geometr�a (tama�o, posic�n y estado) de la ventana principal * de Andami. TODO Pendiente de ver como se asigna un pluginServices para el * launcher. * * @author LWS */ private static void restoreMDIStatus(XMLEntity xml) { if (xml == null) xml = new XMLEntity(); // restore frame size Dimension sz = new Dimension(700, 580); if (xml.contains("MDIFrameSize")) { int[] wh = xml.getIntArrayProperty("MDIFrameSize"); sz = new Dimension(wh[0], wh[1]); } frame.setSize(sz); // restore frame location Point pos = new Point(10, 10); if (xml.contains("MDIFramePos")) { int[] xy = xml.getIntArrayProperty("MDIFramePos"); pos = new Point(xy[0], xy[1]); } frame.setLocation(pos); // restore frame status (Maximized, minimized, etc); int state = java.awt.Frame.MAXIMIZED_BOTH; if (xml.contains("MDIFrameState")) { state = xml.getIntProperty("MDIFrameState"); } frame.setExtendedState(state); } private static XMLEntity saveMDIStatus() { XMLEntity xml = new XMLEntity(); // save frame size int[] wh = new int[2]; wh[0] = frame.getWidth(); wh[1] = frame.getHeight(); xml.putProperty("MDIFrameSize", wh); // save frame location int[] xy = new int[2]; xy[0] = frame.getX(); xy[1] = frame.getY(); xml.putProperty("MDIFramePos", xy); // save frame status xml.putProperty("MDIFrameState", frame.getExtendedState()); return xml; } private static boolean validJVM() { char thirdCharacter = System.getProperty("java.version").charAt(2); if (thirdCharacter < '4') { return false; } else { return true; } } private static void loadPluginsPersistence() throws ConfigurationException { XMLEntity entity = persistenceFromXML(); for (int i = 0; i < entity.getChildrenCount(); i++) { XMLEntity plugin = entity.getChild(i); String pName = plugin .getStringProperty("com.iver.andami.pluginName"); if (pluginsServices.get(pName) != null) { pluginsServices.get(pName).setPersistentXML(plugin); } else { if (pName.startsWith("Andami.Launcher")) restoreMDIStatus(plugin); } } } /** * Salva la persistencia de los plugins. * * @author LWS */ private static void savePluginPersistence() { Iterator<String> i = pluginsConfig.keySet().iterator(); XMLEntity entity = new XMLEntity(); while (i.hasNext()) { String pName = i.next(); PluginServices ps = pluginsServices.get(pName); XMLEntity ent = ps.getPersistentXML(); if (ent != null) { ent.putProperty("com.iver.andami.pluginName", pName); entity.addChild(ent); } } XMLEntity ent = saveMDIStatus(); if (ent != null) { ent.putProperty("com.iver.andami.pluginName", "Andami.Launcher"); entity.addChild(ent); } try { persistenceToXML(entity); } catch (ConfigurationException e1) { logger.error( Messages.getString("Launcher.Se_produjo_un_error_guardando_la_configuracion_de_los_plugins"), e1); } } private static void installPluginsLabels() { Iterator<String> i = pluginsConfig.keySet().iterator(); while (i.hasNext()) { String name = i.next(); PluginConfig pc = pluginsConfig.get(name); PluginServices ps = pluginsServices.get(name); LabelSet[] ls = pc.getLabelSet(); for (int j = 0; j < ls.length; j++) { PluginClassLoader loader = ps.getClassLoader(); try { Class<?> clase = loader.loadClass(ls[j].getClassName()); frame.setStatusBarLabels(clase, ls[j].getLabel()); } catch (ClassNotFoundException e) { logger.error(Messages.getString("Launcher.labelset_class"), e); } } } } private static String configureSkin(XMLEntity xml, String defaultSkin) { if (defaultSkin == null) { for (int i = 0; i < xml.getChildrenCount(); i++) { if (xml.getChild(i).contains("Skin-Selected")) { String className = xml.getChild(i).getStringProperty( "Skin-Selected"); return className; } } } return defaultSkin; } private static void fixSkin(SkinExtension skinExtension, PluginClassLoader pluginClassLoader) throws MDIManagerLoadException { // now insert the skin selected. MDIManagerFactory.setSkinExtension(skinExtension, pluginClassLoader); // MDIManagerFactory.setSkinExtension(se, // ps.getClassLoader()); Class<?> skinClass; try { skinClass = pluginClassLoader.loadClass(skinExtension .getClassName()); com.iver.andami.plugins.IExtension skinInstance = (com.iver.andami.plugins.IExtension) skinClass .newInstance(); // classesExtensions.put(skinClass, skinInstance); // jaume ExtensionDecorator newExtensionDecorator = new ExtensionDecorator( skinInstance, ExtensionDecorator.INACTIVE); classesExtensions.put(skinClass, newExtensionDecorator); } catch (ClassNotFoundException e) { logger.error(Messages .getString("Launcher.No_se_encontro_la_clase_mdi_manager"), e); throw new MDIManagerLoadException(e); } catch (InstantiationException e) { logger.error( Messages.getString("Launcher.No_se_pudo_instanciar_la_clase_mdi_manager"), e); throw new MDIManagerLoadException(e); } catch (IllegalAccessException e) { logger.error( Messages.getString("Launcher.No_se_pudo_acceder_a_la_clase_mdi_manager"), e); throw new MDIManagerLoadException(e); } } /** * DOCUMENT ME! * * @throws MDIManagerLoadException */ private static void skinPlugin(String defaultSkin) throws MDIManagerLoadException { XMLEntity entity = null; try { entity = persistenceFromXML(); } catch (ConfigurationException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } Iterator<String> i = pluginsConfig.keySet().iterator(); SkinExtension skinExtension = null; PluginClassLoader pluginClassLoader = null; ArrayList<SkinExtension> skinExtensions = new ArrayList<SkinExtension>(); while (i.hasNext()) { String name = i.next(); PluginConfig pc = pluginsConfig.get(name); PluginServices ps = pluginsServices.get(name); if (pc.getExtensions().getSkinExtension() != null) { // if (MDIManagerFactory.getSkinExtension() != null) { // logger.warn(Messages.getString( // "Launcher.Dos_skin_extension")); // } SkinExtension[] se = pc.getExtensions().getSkinExtension(); for (int numExten = 0; numExten < se.length; numExten++) { skinExtensions.add(se[numExten]); } for (int j = 0; j < se.length; j++) { String configuredSkin = Launcher.configureSkin(entity, defaultSkin); if (configuredSkin != null && configuredSkin.equals(se[j].getClassName())) { skinExtension = se[j]; pluginClassLoader = ps.getClassLoader(); } } } } if ((skinExtension != null) && (pluginClassLoader != null)) { // configured skin was found fixSkin(skinExtension, pluginClassLoader); } else { if (skinExtensions.contains("com.iver.core.mdiManager.NewSkin")) { // try first NewSkin (from CorePlugin) skinPlugin("com.iver.core.mdiManager.NewSkin"); } else if (skinExtensions.size() > 0) { // try to load the first skin found skinPlugin(skinExtensions.get(0).getClassName()); } else { throw new MDIManagerLoadException("No Skin-Extension installed"); } } } private static void frameIcon(Theme theme) { Iterator<String> i = pluginsConfig.keySet().iterator(); while (i.hasNext()) { String pName = i.next(); PluginConfig pc = pluginsConfig.get(pName); if (pc.getIcon() != null) { if (theme.getIcon() != null) { frame.setIconImage(theme.getIcon().getImage()); } else { ImageIcon icon = PluginServices.getIconTheme().get( pc.getIcon().getSrc()); frame.setIconImage(icon.getImage()); } if (theme.getName() != null) { frame.setTitlePrefix(theme.getName()); } else { frame.setTitlePrefix(pc.getIcon().getText()); } if (theme.getBackgroundImage() != null) { PluginServices.getMDIManager().setBackgroundImage( theme.getBackgroundImage(), theme.getTypeDesktop()); } } } } private static void initializeExtensions() { Iterator<String> i = pluginsOrdered.iterator(); while (i.hasNext()) { String pName = i.next(); logger.debug("Initializing extensions from " + pName); PluginConfig pc = pluginsConfig.get(pName); PluginServices ps = pluginsServices.get(pName); Extension[] exts = pc.getExtensions().getExtension(); TreeMap<Extension, Object> orderedExtensions = new TreeMap<Extension, Object>( new ExtensionComparator()); for (int j = 0; j < exts.length; j++) { if (!exts[j].getActive()) { continue; } if (orderedExtensions.containsKey(exts[j])) { logger.warn(Messages .getString("Launcher.Two_extensions_with_the_same_priority") + exts[j].getClassName()); } orderedExtensions.put(exts[j], null); } Iterator<Extension> e = orderedExtensions.keySet().iterator(); while (e.hasNext()) { Extension extension = e.next(); IExtension extensionInstance; try { Class<?> extensionClass = ps.getClassLoader().loadClass( extension.getClassName()); extensionInstance = (IExtension) extensionClass .newInstance(); // CON DECORATOR // ANTES: classesExtensions.put(extensionClass, // extensionInstance); // AHORA: CREAMOS UNA ExtensionDecorator y asignamos esta // instancia para // poder ampliar con nuevas propiedades (AlwaysVisible, por // ejemplo) // Para crear la nueva clase ExtensionDecorator, le pasamos // como par�metro // la extensi�n original que acabamos de crear // 0-> Inactivo, controla la extension // 1-> Siempre visible // 2-> Invisible ExtensionDecorator newExtensionDecorator = new ExtensionDecorator( extensionInstance, ExtensionDecorator.INACTIVE); classesExtensions .put(extensionClass, newExtensionDecorator); logger.info("Initializing " + extension.getClassName() + "..."); // logger.debug("Initializing " + extension.getClassName()); extensionInstance.initialize(); extensions.add(extensionInstance); // logger.debug(extension.getClassName() + " initialized."); } catch (InstantiationException e1) { logger.error( Messages.getString("Launcher.Error_instanciando_la_extension") + extension.getClassName(), e1); } catch (IllegalAccessException e1) { logger.error( Messages.getString("Launcher.Error_instanciando_la_extension") + extension.getClassName(), e1); } catch (ClassNotFoundException e1) { logger.error( Messages.getString("Launcher.No_se_encontro_la_clase_de_la_extension") + extension.getClassName(), e1); } catch (NoClassDefFoundError e1) { logger.error( Messages.getString("Launcher.Error_localizando_la_clase_de_la_extension") + extension.getClassName(), e1); } } } } private static void postInitializeExtensions() { for (int i = 0; i < extensions.size(); i++) { extensions.get(i).postInitialize(); } } private static void installPluginsMenus() { TreeMap<SortableMenu, Object> orderedMenus = new TreeMap<SortableMenu, Object>( new MenuComparator()); Iterator<String> i = pluginsConfig.keySet().iterator(); while (i.hasNext()) { String pName = i.next(); PluginServices ps = pluginsServices.get(pName); PluginConfig pc = pluginsConfig.get(pName); Extension[] exts = pc.getExtensions().getExtension(); for (int j = 0; j < exts.length; j++) { if (!exts[j].getActive()) { continue; } Menu[] menus = exts[j].getMenu(); for (int k = 0; k < menus.length; k++) { SortableMenu sm = new SortableMenu(ps.getClassLoader(), exts[j], menus[k]); if (orderedMenus.containsKey(sm)) { logger.error(Messages .getString("Launcher.Two_menus_with_the_same_position") + " - " + menus[k].getText() + " - " + exts[j].getClassName()); } orderedMenus.put(sm, null); } } // Se instalan las extensiones de MDI SkinExtension[] skinExts = pc.getExtensions().getSkinExtension(); for (int j = 0; j < skinExts.length; j++) { if (skinExts[j] != null) { Menu[] menu = skinExts[j].getMenu(); for (int k = 0; k < menu.length; k++) { SortableMenu sm = new SortableMenu(ps.getClassLoader(), skinExts[j], menu[k]); if (orderedMenus.containsKey(sm)) { logger.error(Messages .getString("Launcher.Two_menus_with_the_same_position") + skinExts[j].getClassName()); } orderedMenus.put(sm, null); } } } } // Se itera por los menus ordenados Iterator<SortableMenu> e = orderedMenus.keySet().iterator(); // Se ordenan los menues while (e.hasNext()) { try { SortableMenu sm = e.next(); frame.addMenu(sm.loader, sm.extension, sm.menu); } catch (ClassNotFoundException ex) { logger.error( Messages.getString("Launcher.No_se_encontro_la_clase_de_la_extension"), ex); } } } /** * Installs the menus, toolbars, actiontools, selectable toolbars and * combos. The order in which they are shown is determined here. */ private static void installPluginsControls() { Iterator<String> i = pluginsConfig.keySet().iterator(); HashMap<Extension, PluginServices> extensionPluginServices = new HashMap<Extension, PluginServices>(); HashMap<Extension, PluginConfig> extensionPluginConfig = new HashMap<Extension, PluginConfig>(); TreeMap<Extension, Object> orderedExtensions = new TreeMap<Extension, Object>( new ExtensionComparator()); // First of all, sort the extensions. // We need to iterate on the plugins, and iterate on each plugin's // extensions // (each plugin may contain one or more extensions) while (i.hasNext()) { // iterate on the plugins String pName = i.next(); PluginConfig pc = pluginsConfig.get(pName); PluginServices ps = pluginsServices.get(pName); Extension[] exts = pc.getExtensions().getExtension(); for (int j = 0; j < exts.length; j++) { // iterate on the extensions if (exts[j].getActive()) { if (orderedExtensions.containsKey(exts[j])) { logger.error(Messages .getString("Launcher.Two_extensions_with_the_same_priority") + exts[j].getClassName()); } orderedExtensions.put(exts[j], null); extensionPluginServices.put(exts[j], ps); extensionPluginConfig.put(exts[j], pc); } } } TreeMap<SortableTool, Object> orderedTools = new TreeMap<SortableTool, Object>( new ToolComparator()); Iterator<Extension> e = orderedExtensions.keySet().iterator(); // sort the toolbars and tools from 'normal' extensions (actiontools, // selectabletools) // and load the combo-scales and combo-buttons for the status bar while (e.hasNext()) { Extension ext = e.next(); ToolBar[] toolbars = ext.getToolBar(); // get tools from toolbars for (int k = 0; k < toolbars.length; k++) { ActionTool[] tools = toolbars[k].getActionTool(); for (int t = 0; t < tools.length; t++) { SortableTool sm = new SortableTool(extensionPluginServices .get(ext).getClassLoader(), ext, toolbars[k], tools[t]); orderedTools.put(sm, null); } SelectableTool[] sTools = toolbars[k].getSelectableTool(); for (int t = 0; t < sTools.length; t++) { SortableTool sm = new SortableTool(extensionPluginServices .get(ext).getClassLoader(), ext, toolbars[k], sTools[t]); orderedTools.put(sm, null); } } // get controls for statusBar PluginServices ps = extensionPluginServices.get(ext); PluginClassLoader loader = ps.getClassLoader(); // ArrayList componentList = new ArrayList(); ComboScale[] comboScaleArray = ext.getComboScale(); for (int k = 0; k < comboScaleArray.length; k++) { org.gvsig.gui.beans.controls.comboscale.ComboScale combo = new org.gvsig.gui.beans.controls.comboscale.ComboScale(); String label = comboScaleArray[k].getLabel(); if (label != null) combo.setLabel(label); String name = comboScaleArray[k].getName(); if (name != null) combo.setName(name); String[] elementsString = ((String) comboScaleArray[k] .getElements()).split(";"); long[] elements = new long[elementsString.length]; for (int currentElem = 0; currentElem < elementsString.length; currentElem++) { try { elements[currentElem] = Long .parseLong(elementsString[currentElem]); } catch (NumberFormatException nfex1) { logger.error(ext.getClassName() + " -- " + Messages .getString("error_parsing_comboscale_elements")); elements[currentElem] = 0; } } combo.setItems(elements); try { long value = Long.parseLong((String) comboScaleArray[k] .getValue()); combo.setScale(value); } catch (NumberFormatException nfex2) { logger.error(ext.getClassName() + " -- " + Messages .getString("error_parsing_comboscale_value")); } try { frame.addStatusBarControl( loader.loadClass(ext.getClassName()), combo); } catch (ClassNotFoundException e1) { logger.error( Messages.getString("Launcher.error_getting_class_loader_for_status_bar_control"), e1); } } ComboButton[] comboButtonArray = ext.getComboButton(); for (int k = 0; k < comboButtonArray.length; k++) { ComboButtonElement[] elementList = comboButtonArray[k] .getComboButtonElement(); org.gvsig.gui.beans.controls.combobutton.ComboButton combo = new org.gvsig.gui.beans.controls.combobutton.ComboButton(); String name = comboButtonArray[k].getName(); if (name != null) combo.setName(name); for (int currentElement = 0; currentElement < elementList.length; currentElement++) { ComboButtonElement element = elementList[currentElement]; ImageIcon icon; URL iconLocation = loader.getResource(element.getIcon()); if (iconLocation == null) logger.error(Messages.getString("Icon_not_found_") + element.getIcon()); else { icon = new ImageIcon(iconLocation); JButton button = new JButton(icon); combo.addButton(button); button.setActionCommand(element.getActionCommand()); } } try { frame.addStatusBarControl( loader.loadClass(ext.getClassName()), combo); } catch (ClassNotFoundException e1) { logger.error( Messages.getString("Launcher.error_getting_class_loader_for_status_bar_control"), e1); } } } // Add the tools from MDI extensions to the ordered tool-list, so that // we get a sorted list containing all the tools i = pluginsConfig.keySet().iterator(); while (i.hasNext()) { String pName = i.next(); PluginConfig pc = pluginsConfig.get(pName); PluginServices ps = pluginsServices.get(pName); SkinExtension[] skinExts = pc.getExtensions().getSkinExtension(); for (int j = 0; j < skinExts.length; j++) { if (skinExts[j] != null) { ToolBar[] toolbars = skinExts[j].getToolBar(); for (int k = 0; k < toolbars.length; k++) { ActionTool[] tools = toolbars[k].getActionTool(); for (int t = 0; t < tools.length; t++) { SortableTool stb = new SortableTool( ps.getClassLoader(), skinExts[j], toolbars[k], tools[t]); orderedTools.put(stb, null); } SelectableTool[] sTools = toolbars[k] .getSelectableTool(); for (int t = 0; t < sTools.length; t++) { SortableTool stb = new SortableTool( ps.getClassLoader(), skinExts[j], toolbars[k], sTools[t]); orderedTools.put(stb, null); } } } } // Install popup menus PopupMenus pus = pc.getPopupMenus(); if (pus != null) { PopupMenu[] menus = pus.getPopupMenu(); for (int j = 0; j < menus.length; j++) { frame.addPopupMenu(ps.getClassLoader(), menus[j]); } } } // loop on the ordered extension list, to add them to the interface in // an ordered way Iterator<SortableTool> t = orderedTools.keySet().iterator(); while (t.hasNext()) { try { SortableTool stb = t.next(); if (stb.actiontool != null) frame.addTool(stb.loader, stb.extension, stb.toolbar, stb.actiontool); else frame.addTool(stb.loader, stb.extension, stb.toolbar, stb.selectabletool); } catch (ClassNotFoundException ex) { logger.error( Messages.getString("Launcher.No_se_encontro_la_clase_de_la_extension"), ex); } } } /** * Adds new plugins to the the andami-config file. */ private static void updateAndamiConfig() { HashSet<String> olds = new HashSet<String>(); Plugin[] plugins = andamiConfig.getPlugin(); for (int i = 0; i < plugins.length; i++) { olds.add(plugins[i].getName()); } Iterator<PluginServices> i = pluginsServices.values().iterator(); while (i.hasNext()) { PluginServices ps = i.next(); if (!olds.contains(ps.getPluginName())) { Plugin p = new Plugin(); p.setName(ps.getPluginName()); p.setUpdate(false); andamiConfig.addPlugin(p); } } } private static void pluginsClassLoaders() { HashSet<String> instalados = new HashSet<String>(); // Se itera hasta que est�n todos instalados while (instalados.size() != pluginsConfig.size()) { boolean circle = true; // Hacemos una pasada por todos los plugins Iterator<String> i = pluginsConfig.keySet().iterator(); while (i.hasNext()) { String pluginName = i.next(); PluginConfig config = pluginsConfig.get(pluginName); if (instalados.contains(pluginName)) { continue; } // Se obtienen las dependencias y sus class loaders boolean ready = true; Depends[] dependencies = config.getDepends(); PluginClassLoader[] loaders = new PluginClassLoader[dependencies.length]; for (int j = 0; j < dependencies.length; j++) { if (pluginsConfig.get(dependencies[j].getPluginName()) == null) { logger.error(Messages .getString("Launcher.Dependencia_no_resuelta_en_plugin") + pluginName + ": " + dependencies[j].getPluginName()); continue; } if (!instalados.contains(dependencies[j].getPluginName())) { ready = false; } else { loaders[j] = pluginsServices.get( dependencies[j].getPluginName()) .getClassLoader(); } } // Si no est�n sus dependencias satisfechas se aborta la // instalaci�n if (!ready) { continue; } // Se genera el class loader String jardir = config.getLibraries().getLibraryDir(); File jarDir = new File(andamiConfig.getPluginsDirectory() + File.separator + pluginName + File.separator + jardir); File[] jarFiles = jarDir.listFiles(new FileFilter() { public boolean accept(File pathname) { return (pathname.getName().toUpperCase() .endsWith(".JAR")) || (pathname.getName().toUpperCase() .endsWith(".ZIP")); } }); URL[] urls = new URL[jarFiles.length]; for (int j = 0; j < jarFiles.length; j++) { try { urls[j] = new URL("file:" + jarFiles[j]); } catch (MalformedURLException e) { logger.error(Messages .getString("Launcher.No_se_puede_acceder_a") + jarFiles[j]); } } PluginClassLoader loader; try { loader = new PluginClassLoader(urls, andamiConfig.getPluginsDirectory() + File.separator + pluginName, Launcher.class.getClassLoader(), loaders); PluginServices ps = new PluginServices(loader); pluginsServices.put(ps.getPluginName(), ps); instalados.add(pluginName); // FJP: Los metemos ordenados para luego no cargar uno que // necesita de otro antes de tiempo. Esto lo usaremos al // inicializar los plugins pluginsOrdered.add(pluginName); circle = false; } catch (IOException e) { logger.error( Messages.getString("Launcher.Error_con_las_librerias_del_plugin"), e); pluginsConfig.remove(pluginName); i = pluginsConfig.keySet().iterator(); } } if (circle) { logger.error(Messages .getString("Launcher.Hay_dependencias_circulares")); break; } } // Se eliminan los plugins que no fueron instalados Iterator<String> i = pluginsConfig.keySet().iterator(); while (i.hasNext()) { String pluginName = i.next(); PluginServices ps = pluginsServices.get(pluginName); if (ps == null) { pluginsConfig.remove(pluginName); i = pluginsConfig.keySet().iterator(); } } } private static void pluginsMessages() { Iterator<String> iterator = pluginsOrdered.iterator(); PluginConfig config; PluginServices ps; while (iterator.hasNext()) { String pluginName = iterator.next(); config = pluginsConfig.get(pluginName); ps = pluginsServices.get(pluginName); if (config.getResourceBundle() != null && !config.getResourceBundle().getName().equals("")) { // add the locale files associated with the plugin org.gvsig.i18n.Messages.addResourceFamily(config .getResourceBundle().getName(), ps.getClassLoader(), pluginName); } } } static PluginServices getPluginServices(String name) { return pluginsServices.get(name); } static String getPluginsDir() { return andamiConfig.getPluginsDirectory(); } static void setPluginsDir(String s) { andamiConfig.setPluginsDirectory(s); } static MDIFrame getMDIFrame() { return frame; } private static void loadPlugins(String pluginsDirectory) { File pDir = new File(pluginsDirectory); if (!pDir.exists()) { logger.error("\n\tPlugins directory not found: " + pDir.getAbsolutePath() + "\n\tDid you specify the correct directory in the Launch Configuration parameters?\n\tExiting now..."); System.exit(-1); return; } File[] pluginDirs = pDir.listFiles(); if (pluginDirs.length == 0) { logger.error("\n\tPlugins directory is empty: " + pDir.getAbsolutePath() + "Did you specify the correct directory in the Launch Configuration parameters?\n\tExiting now..."); System.exit(-1); return; } for (int i = 0; i < pluginDirs.length; i++) { if (pluginDirs[i].isDirectory()) { File configXml = new File(pluginDirs[i].getAbsolutePath() + File.separator + "config.xml"); try { FileInputStream is = new FileInputStream(configXml); Reader xml = com.iver.utiles.xml.XMLEncodingUtils .getReader(is); if (xml == null) { // the encoding was not correctly detected, use system // default xml = new FileReader(configXml); } else { // use a buffered reader to improve performance xml = new BufferedReader(xml); } PluginConfig pConfig = (PluginConfig) PluginConfig .unmarshal(xml); pluginsConfig.put(pluginDirs[i].getName(), pConfig); } catch (FileNotFoundException e) { logger.info(Messages .getString("Launcher.Ignorando_el_directorio") + pluginDirs[i].getAbsolutePath() + Messages .getString("Launcher.config_no_encontrado")); } catch (MarshalException e) { logger.info( Messages.getString("Launcher.Ignorando_el_directorio") + pluginDirs[i].getAbsolutePath() + Messages .getString("Launcher.config_mal_formado"), e); } catch (ValidationException e) { logger.info( Messages.getString("Launcher.Ignorando_el_directorio") + pluginDirs[i].getAbsolutePath() + Messages .getString("Launcher.config_mal_formado"), e); } } } if (pluginsConfig.size() == 0) { logger.error("\n\tNo valid plugin was found. The plugins directory currently is: " + pDir.getAbsolutePath() + "\n\tDid you specify the correct directory in the Launch Configuration parameters?\n\tExiting now..."); System.exit(-1); return; } } private static Locale getLocale(String language, String country, String variant) { if (variant != null) { return new Locale(language, country, variant); } else if (country != null) { return new Locale(language, country); } else if (language != null) { return new Locale(language); } else { return new Locale("es"); } } private static void andamiConfigToXML(String file) throws IOException, MarshalException, ValidationException { // write on a temporary file in order to not destroy current file if // there is some problem while marshaling File tmpFile = new File(file + "-" + DateTime.getCurrentDate().getTime()); File xml = new File(file); File parent = xml.getParentFile(); parent.mkdirs(); BufferedOutputStream os = new BufferedOutputStream( new FileOutputStream(tmpFile)); OutputStreamWriter writer = new OutputStreamWriter(os, CASTORENCODING); andamiConfig.marshal(writer); writer.close(); // if marshaling process finished correctly, move the file to the // correct one xml.delete(); if (!tmpFile.renameTo(xml)) { // if rename was not succesful, try copying it FileChannel sourceChannel = new FileInputStream(tmpFile) .getChannel(); FileChannel destinationChannel = new FileOutputStream(xml) .getChannel(); sourceChannel.transferTo(0, sourceChannel.size(), destinationChannel); sourceChannel.close(); destinationChannel.close(); } } private static void andamiConfigFromXML(String file) throws ConfigurationException { File xml = new File(file); InputStreamReader reader = null; try { // Se lee la configuraci�n reader = XMLEncodingUtils.getReader(xml); andamiConfig = (AndamiConfig) AndamiConfig.unmarshal(reader); } catch (FileNotFoundException e) { // Si no existe se ponen los valores por defecto andamiConfig = getDefaultAndamiConfig(); } catch (MarshalException e) { // try to close the stream, maybe it remains open if (reader != null) { try { reader.close(); } catch (IOException e1) { } } // if there was a problem reading the file, backup it and create a // new one with default values String backupFile = file + "-" + DateTime.getCurrentDate().getTime(); NotificationManager .addError( Messages.getString("Error_reading_andami_config_New_file_created_A_backup_was_made_on_") + backupFile, new ConfigurationException(e)); xml.renameTo(new File(backupFile)); andamiConfig = getDefaultAndamiConfig(); } catch (ValidationException e) { throw new ConfigurationException(e); } } private static AndamiConfig getDefaultAndamiConfig() { AndamiConfig andamiConfig = new AndamiConfig(); Andami andami = new Andami(); andami.setUpdate(true); andamiConfig.setAndami(andami); andamiConfig.setLocaleCountry(Locale.getDefault().getCountry()); andamiConfig.setLocaleLanguage(Locale.getDefault().getLanguage()); andamiConfig.setLocaleVariant(Locale.getDefault().getVariant()); if (System.getProperty("javawebstart.version") != null) // Es java web // start) { andamiConfig.setPluginsDirectory(new File(appHomeDir + "extensiones").getAbsolutePath()); } else { andamiConfig.setPluginsDirectory(new File(appName + File.separator + "extensiones").getAbsolutePath()); } andamiConfig.setPlugin(new Plugin[0]); return andamiConfig; } private static XMLEntity persistenceFromXML() throws ConfigurationException { File xml = new File(pluginsPersistencePath); if (xml.exists()) { InputStreamReader reader = null; try { reader = XMLEncodingUtils.getReader(xml); XmlTag tag = (XmlTag) XmlTag.unmarshal(reader); return new XMLEntity(tag); } catch (FileNotFoundException e) { throw new ConfigurationException(e); } catch (MarshalException e) { // try to reopen with default encoding (for backward // compatibility) try { reader = new FileReader(xml); XmlTag tag = (XmlTag) XmlTag.unmarshal(reader); return new XMLEntity(tag); } catch (MarshalException ex) { // try to close the stream, maybe it remains open if (reader != null) { try { reader.close(); } catch (IOException e1) { } } // backup the old file String backupFile = pluginsPersistencePath + "-" + DateTime.getCurrentDate().getTime(); NotificationManager .addError( Messages.getString("Error_reading_plugin_persinstence_New_file_created_A_backup_was_made_on_") + backupFile, new ConfigurationException(e)); xml.renameTo(new File(backupFile)); // create a new, empty configuration return new XMLEntity(); } catch (FileNotFoundException ex) { return new XMLEntity(); } catch (ValidationException ex) { throw new ConfigurationException(e); } } catch (ValidationException e) { throw new ConfigurationException(e); } } else { return new XMLEntity(); } } private static void persistenceToXML(XMLEntity entity) throws ConfigurationException { // write on a temporary file in order to not destroy current file if // there is some problem while marshaling File tmpFile = new File(pluginsPersistencePath + "-" + DateTime.getCurrentDate().getTime()); File xml = new File(pluginsPersistencePath); OutputStreamWriter writer = null; try { writer = new OutputStreamWriter(new FileOutputStream(tmpFile), CASTORENCODING); entity.getXmlTag().marshal(writer); writer.close(); // if marshaling process finished correctly, move the file to the // correct one xml.delete(); if (!tmpFile.renameTo(xml)) { // if rename was not succesful, try copying it FileChannel sourceChannel = new FileInputStream(tmpFile) .getChannel(); FileChannel destinationChannel = new FileOutputStream(xml) .getChannel(); sourceChannel.transferTo(0, sourceChannel.size(), destinationChannel); sourceChannel.close(); destinationChannel.close(); } } catch (FileNotFoundException e) { throw new ConfigurationException(e); } catch (MarshalException e) { // try to close the stream, maybe it remains open if (writer != null) { try { writer.close(); } catch (IOException e1) { } } } catch (ValidationException e) { throw new ConfigurationException(e); } catch (IOException e) { throw new ConfigurationException(e); } } static MDIFrame getFrame() { return frame; } /** * Gracefully closes the application. It shows dialogs to save data, finish * processes, etc, then it terminates the extensions, removes temporal files * and finally exits. */ public synchronized static void closeApplication() { TerminationProcess terminationProcess = (new Launcher()).new TerminationProcess(); terminationProcess.run(); } static HashMap<Class<?>, ExtensionDecorator> getClassesExtensions() { return classesExtensions; } private static Extensions[] getExtensions() { ArrayList<Extensions> array = new ArrayList<Extensions>(); Iterator<PluginConfig> iter = pluginsConfig.values().iterator(); while (iter.hasNext()) { array.add(iter.next().getExtensions()); } return array.toArray(new Extensions[0]); } public static Iterator<IExtension> getExtensionIterator() { return extensions.iterator(); } public static HashMap<String, PluginConfig> getPluginConfig() { return pluginsConfig; } public static Extension getExtension(String s) { Extensions[] exts = getExtensions(); for (int i = 0; i < exts.length; i++) { for (int j = 0; j < exts[i].getExtensionCount(); j++) { if (exts[i].getExtension(j).getClassName().equals(s)) { return exts[i].getExtension(j); } } } return null; } public static AndamiConfig getAndamiConfig() { return andamiConfig; } private static class ExtensionComparator implements Comparator<Extension> { public int compare(Extension e1, Extension e2) { if (!e1.hasPriority() && !e2.hasPriority()) { return -1; } if (e1.hasPriority() && !e2.hasPriority()) { return Integer.MIN_VALUE; } if (e2.hasPriority() && !e1.hasPriority()) { return Integer.MAX_VALUE; } if (e1.getPriority() != e2.getPriority()) { return e2.getPriority() - e1.getPriority(); } else { return (e2.toString().compareTo(e1.toString())); } } } private static class MenuComparator implements Comparator<SortableMenu> { public int compare(SortableMenu sm1, SortableMenu sm2) { if (!sm1.menu.hasPosition() && !sm2.menu.hasPosition()) { return 1; } if (sm1.menu.hasPosition() && !sm2.menu.hasPosition()) { return Integer.MIN_VALUE; } if (sm2.menu.hasPosition() && !sm1.menu.hasPosition()) { return Integer.MAX_VALUE; } if (sm1.menu.getPosition() != sm2.menu.getPosition()) { // we don't return 0 unless both objects are the same, otherwise // the objects get overwritten in the treemap return sm1.menu.getPosition() - sm2.menu.getPosition(); } else { return (sm1.toString().compareTo(sm2.toString())); } } } private static class SortableMenu { public PluginClassLoader loader; public Menu menu; public SkinExtensionType extension; public SortableMenu(PluginClassLoader loader, SkinExtensionType skinExt, Menu menu2) { extension = skinExt; menu = menu2; this.loader = loader; } } private static class SortableTool { public PluginClassLoader loader; public ToolBar toolbar; public ActionTool actiontool; public SelectableTool selectabletool; public SkinExtensionType extension; public SortableTool(PluginClassLoader loader, SkinExtensionType skinExt, ToolBar toolbar2, ActionTool actiontool2) { extension = skinExt; toolbar = toolbar2; actiontool = actiontool2; this.loader = loader; } public SortableTool(PluginClassLoader loader, SkinExtensionType skinExt, ToolBar toolbar2, SelectableTool selectabletool2) { extension = skinExt; toolbar = toolbar2; selectabletool = selectabletool2; this.loader = loader; } } private static class ToolBarComparator implements Comparator<SortableTool> { public int compare(SortableTool e1, SortableTool e2) { // if the toolbars have the same name, they are considered to be // the same toolbar, so we don't need to do further comparing if (e1.toolbar.getName().equals(e2.toolbar.getName())) return 0; if (!e1.toolbar.hasPosition() && !e2.toolbar.hasPosition()) { return 1; } if (e1.toolbar.hasPosition() && !e2.toolbar.hasPosition()) { return Integer.MIN_VALUE; } if (e2.toolbar.hasPosition() && !e1.toolbar.hasPosition()) { return Integer.MAX_VALUE; } if (e1.toolbar.getPosition() != e2.toolbar.getPosition()) return e1.toolbar.getPosition() - e2.toolbar.getPosition(); if (e1.toolbar.getActionTool().equals(e2.toolbar.getActionTool()) && e1.toolbar.getSelectableTool().equals( e2.toolbar.getSelectableTool())) { return 0; } return (e1.toolbar.toString().compareTo(e2.toolbar.toString())); } } /** * <p> * This class is used to compare tools (selectabletool and actiontool), * using the "position" attribute. * </p> * <p> * The ordering criteria are: * </p> * <ul> * <li>If the tools are placed in different toolbars, they use the toolbars' * order. (using the ToolBarComparator).</li> * <li></li> * <li>If any of the tools has not 'position' attribute, the tool which * <strong>has</strong> the attribute will be placed first.</li> * <li>If both tools have the same position (or they don't have a 'position' * attribute), the priority of the extensions where the tool is defined.</li> * </ul> * * @author cesar * @version $Revision: 33300 $ */ private static class ToolComparator implements Comparator<SortableTool> { private static ToolBarComparator toolBarComp = new ToolBarComparator(); public int compare(SortableTool st1, SortableTool st2) { // compare the toolbars which contain the tools int result = toolBarComp.compare(st1, st2); if (result != 0) { // if the toolbars are different, use their order return result; } // otherwise, compare the tools int e1Position = -1, e2Position = -1; if (st1.actiontool != null) { if (st1.actiontool.hasPosition()) e1Position = st1.actiontool.getPosition(); } else if (st1.selectabletool != null) { if (st1.selectabletool.hasPosition()) e1Position = st1.selectabletool.getPosition(); } if (st2.actiontool != null) { if (st2.actiontool.hasPosition()) e2Position = st2.actiontool.getPosition(); } else if (st2.selectabletool != null) { if (st2.selectabletool.hasPosition()) e2Position = st2.selectabletool.getPosition(); } if (e1Position == -1 && e2Position != -1) { return 1; } if (e1Position != -1 && e2Position == -1) { return -1; } if (e1Position != -1 && e2Position != -1) { result = e1Position - e2Position; // we don't return 0 unless both objects are the same, otherwise // the objects get overwritten in the treemap if (result != 0) return result; } return st1.toString().compareTo(st2.toString()); } } /** * validates the user before starting gvsig * */ private static void validate() { IAuthentication session = null; try { session = (IAuthentication) Class.forName( "com.iver.andami.authentication.Session").newInstance(); } catch (ClassNotFoundException e) { return; } catch (InstantiationException e) { return; } catch (IllegalAccessException e) { return; } session.setPluginDirectory(andamiConfig.getPluginsDirectory()); if (session.validationRequired()) { if (session.Login()) { System.out.println("You are logged in"); } else { JOptionPane.showMessageDialog( (Component) PluginServices.getMainFrame(), "You are not logged in"); // System.exit(0); } PluginServices.setAuthentication(session); } } public static String getDefaultLookAndFeel() { String osName = System.getProperty("os.name"); if (osName.length() > 4 && osName.substring(0, 5).toLowerCase().equals("linux")) return nonWinDefaultLookAndFeel; if (osName.toLowerCase().startsWith("mac os x")) return "ch.randelshofer.quaqua.QuaquaLookAndFeel"; return UIManager.getSystemLookAndFeelClassName(); } /** * Gets the ISO 839 two-characters-long language code matching the provided * language code (which may be an ISO 839-2/T three-characters-long code or * an ISO 839-1 two-characters-long code). * * If the provided parameter is already two characters long, it returns the * parameter without any modification. * * @param langCode * A language code representing either an ISO 839-2/T language * code or an ISO 839-1 code. * @return A two-characters-long code specifying an ISO 839 language code. */ private static String normalizeLanguageCode(String langCode) { final String fileName = "iso_639.tab"; if (langCode.length() == 2) return langCode; else if (langCode.length() == 3) { if (langCode.equals("va") || langCode.equals("val")) { // special // case for // Valencian return "ca"; } URL isoCodes = Launcher.class.getClassLoader() .getResource(fileName); if (isoCodes != null) { try { BufferedReader reader = new BufferedReader( new InputStreamReader(isoCodes.openStream(), "ISO-8859-1")); String line; while ((line = reader.readLine()) != null) { String[] language = line.split("\t"); if (language[0].equals(langCode)) // first column is the // three characters // code return language[2]; // third column i the two // characters code } } catch (IOException ex) { logger.error( Messages.getString("Error_reading_isocodes_file"), ex); return "es"; } } else { logger.error(Messages.getString("Error_reading_isocodes_file")); return "es"; } } return "es"; } /** * Configures the locales (languages and local resources) to be used by the * application. * * First it tries to get the locale from the command line parameters, then * the andami-config file is checked. * * The locale name is normalized to get a two characters language code as * defined by ISO-639-1 (although ISO-639-2/T three characters codes are * also accepted from the command line or the configuration file). * * Finally, the gvsig-i18n library and the default locales for Java and * Swing are configured. * */ private static void configureLocales(String[] args) { // Configurar el locale String localeStr = null; /* * for (int i=2; i < args.length; i++) { int index = * args[i].indexOf("language="); if (index != -1) localeStr = * args[i].substring(index+9); } */ localeStr = PluginServices.getArgumentByName("language"); if (localeStr == null) { localeStr = andamiConfig.getLocaleLanguage(); } localeStr = normalizeLanguageCode(localeStr); locale = getLocale(localeStr, andamiConfig.getLocaleCountry(), andamiConfig.getLocaleVariant()); Locale.setDefault(locale); JComponent.setDefaultLocale(locale); org.gvsig.i18n.Messages.addLocale(locale); // add english and spanish as fallback languages if (localeStr.equals("es") || localeStr.equals("ca") || localeStr.equals("gl") || localeStr.equals("eu") || localeStr.equals("va")) { // prefer Spanish for languages spoken in Spain org.gvsig.i18n.Messages.addLocale(new Locale("es")); org.gvsig.i18n.Messages.addLocale(new Locale("en")); } else { // prefer English for the rest org.gvsig.i18n.Messages.addLocale(new Locale("en")); org.gvsig.i18n.Messages.addLocale(new Locale("es")); } org.gvsig.i18n.Messages.addResourceFamily("com.iver.andami.text", "com.iver.andami.text"); } /** * Gets Home Directory location of the application. May be set from outside * the aplication by means of -DgvSIG.home=C:/data/gvSIG, where gvSIG its * the name of the application * * @return */ public static String getAppHomeDir() { return appHomeDir; } /** * Sets Home Directory location of the application. May be set from outside * the aplication by means of -DgvSIG.home=C:/data/gvSIG, where gvSIG its * the name of the application * * @param appHomeDir */ public static void setAppHomeDir(String appHomeDir) { Launcher.appHomeDir = appHomeDir; } /** * Initialize the extesion that have to take the control of the state of * action controls of the UI of all extensions. <br> * <br> * For use this option you have to add an argument to the command line like * this: <br> * <br> * -exclusiveUI={pathToExtensionClass} <br> * * @see com.iver.andami.plugins.IExtension#isEnabled(IExtension extension) * @see com.iver.andami.plugins.IExtension#isVisible(IExtension extension) */ private static void initializeExclusiveUIExtension() { String name = PluginServices.getArgumentByName("exclusiveUI"); if (name == null) return; Iterator<Class<?>> iter = classesExtensions.keySet().iterator(); int charIndex; Class<?> key; while (iter.hasNext()) { key = iter.next(); charIndex = key.getName().indexOf(name); // System.out.println("key='"+key.getName()+"' name='"+name+"' charIndex="+charIndex); if (charIndex == 0) { IExtension ext = classesExtensions.get(key); if (ext instanceof ExtensionDecorator) ext = ((ExtensionDecorator) ext).getExtension(); if (ext instanceof ExclusiveUIExtension) PluginServices .setExclusiveUIExtension((ExclusiveUIExtension) ext); break; } } logger.error(Messages .getString("No_se_encontro_la_extension_especificada_en_el_parametro_exclusiveUI") + " '" + name + "'"); } // public static void initIconThemes() { // // load the iconTheme // IconThemeManager iconManager = new IconThemeManager(); // PluginServices.setIconThemeManager(iconManager); // IconThemeInfo selectedTheme = iconManager.readConfig(); // if (selectedTheme!=null) { // iconManager.setDefault(selectedTheme); // logger.info("Setting the icon theme: "+selectedTheme.toVerboseString()); // } // else { // // set the default dir and try to load the default theme // try { // iconManager.setThemesDir(new File("iconThemes")); // IconThemeInfo[] list = iconManager.list(); // // for (int i=0; i<list.length; i++) { // if (list[i].getResourceName().equals("iconThemes/icons")) { // iconManager.setDefault(list[i]); // logger.info("Setting the default icon theme: "+list[i].toVerboseString()); // return; // } // } // } catch (FileNotFoundException e) { // logger.info("IconTheme basedir does not exist"); // } // // create an empty theme // IconThemeInfo info = new IconThemeInfo(); // info.setName("No theme loaded"); // info.setResource(null); // null resource means that no real theme is // loaded // info.setDescription("No theme loaded"); // info.setVersion("0"); // iconManager.setDefault(new IconTheme(info)); // logger.info("Setting an empty icon theme"); // // } // } public static void initIconThemes() { IconThemeManager iconManager = IconThemeManager.getIconThemeManager(); IIconTheme icontheme = iconManager.getIconThemeFromConfig(); if (icontheme != null) { iconManager.setCurrent(icontheme); } } /** * Manages Andami termination process * * @author Cesar Martinez Izquierdo <cesar.martinez@iver.es> */ public class TerminationProcess { private boolean proceed = false; private UnsavedDataPanel panel = null; public void run() { int exit = manageUnsavedData(); if (exit == JOptionPane.NO_OPTION || exit == JOptionPane.CLOSED_OPTION) { // the user doesn't want to exit return; } closeAndami(); } /** * Finishes the application without asking user if want or not to save * unsaved data. */ public void closeAndami() { // Configuraci�n de Andami try { andamiConfigToXML(andamiConfigPath); } catch (MarshalException e) { logger.error( Messages.getString("Launcher.No_se_pudo_guardar_la_configuracion_de_andami"), e); } catch (ValidationException e) { logger.error( Messages.getString("Launcher.No_se_pudo_guardar_la_configuracion_de_andami"), e); } catch (IOException e) { logger.error( Messages.getString("Launcher.No_se_pudo_guardar_la_configuracion_de_andami"), e); } // Persistencia de los plugins savePluginPersistence(); // Finalize all the extensions finalizeExtensions(); // Clean any temp data created Utilities.cleanUpTempFiles(); // Para la depuraci�n de memory leaks System.gc(); System.exit(0); } /** * Exectutes the terminate method for all the extensions, in the reverse * order they were initialized * */ private void finalizeExtensions() { for (int i = extensions.size() - 1; i >= 0; i--) { extensions.get(i).terminate(); } } private ArrayList<IUnsavedData> getUnsavedData() { ArrayList<IUnsavedData> unsavedDataList = new ArrayList<IUnsavedData>(); IExtension exclusiveExtension = PluginServices .getExclusiveUIExtension(); for (int i = extensions.size() - 1; i >= 0; i--) { IExtension extensionInstance = extensions.get(i); IExtensionStatus status = null; if (exclusiveExtension != null) { status = exclusiveExtension.getStatus(extensionInstance); } else { status = extensionInstance.getStatus(); } if (status != null) { if (status.hasUnsavedData()) { IUnsavedData[] array = status.getUnsavedData(); for (int element = 0; element < array.length; element++) { unsavedDataList.add(array[element]); } } } } return unsavedDataList; } public UnsavedDataPanel getUnsavedDataPanel() { if (panel == null) { panel = new UnsavedDataPanel(new IUnsavedData[0]); } return panel; } /** * Checks if the extensions have some unsaved data, and shows a dialog * to allow saving it. This dialog also allows to don't exit Andami. * * @return true if the user confirmed he wishes to exit, false otherwise */ public int manageUnsavedData() { ArrayList<IUnsavedData> unsavedDataList = getUnsavedData(); // there was no unsaved data if (unsavedDataList.size() == 0) { int option = JOptionPane.showConfirmDialog(frame, Messages.getString("MDIFrame.quiere_salir"), Messages.getString("MDIFrame.salir"), JOptionPane.YES_NO_OPTION); return option; } // it does not work if we directly cast the array IUnsavedData[] unsavedDataArray; unsavedDataArray = new IUnsavedData[unsavedDataList.size()]; System.arraycopy(unsavedDataList.toArray(), 0, unsavedDataArray, 0, unsavedDataList.size()); UnsavedDataPanel panel = getUnsavedDataPanel(); panel.setUnsavedDataArray(unsavedDataArray); panel.addActionListener(panel.new UnsavedDataPanelListener() { public void cancel(UnsavedDataPanel panel) { proceed(false); PluginServices.getMDIManager().closeWindow(panel); } public void discard(UnsavedDataPanel panel) { proceed(true); PluginServices.getMDIManager().closeWindow(panel); } public void accept(UnsavedDataPanel panel) { IUnsavedData[] unsavedDataArray = panel .getSelectedsUnsavedData(); boolean saved; for (int i = 0; i < unsavedDataArray.length; i++) { try { saved = unsavedDataArray[i].saveData(); } catch (Exception ex) { PluginServices.getLogger().error( "Error saving" + unsavedDataArray[i] .getResourceName(), ex); saved = false; } if (!saved) { JOptionPane.showMessageDialog( panel, PluginServices .getText(this, "The_following_resource_could_not_be_saved_") + "\n" + unsavedDataArray[i] .getResourceName() + " -- " + unsavedDataArray[i] .getDescription(), PluginServices.getText(this, "Resource_was_not_saved"), JOptionPane.ERROR_MESSAGE); ArrayList<IUnsavedData> unsavedDataList = getUnsavedData(); // it does not work if we directly cast the array unsavedDataArray = new IUnsavedData[unsavedDataList .size()]; System.arraycopy(unsavedDataList.toArray(), 0, unsavedDataArray, 0, unsavedDataList.size()); panel.setUnsavedDataArray(unsavedDataArray); return; } } proceed(true); PluginServices.getMDIManager().closeWindow(panel); } }); PluginServices.getMDIManager().addWindow(panel); if (proceed) { return JOptionPane.YES_OPTION; } else { return JOptionPane.NO_OPTION; } } private void proceed(boolean proceed) { this.proceed = proceed; } } public static TerminationProcess getTerminationProcess() { return (new Launcher()).new TerminationProcess(); } }